/*
Hey you! You are reading my code!
I want to say that my code is far from perfect, and if you see that I'm doing something
in a really wrong/dumb way, please give me advices instead of saying "LOL U BAD CODER"
        Thanks
      - MadJawa
*/
LaserLib = LaserLib or {};

function LaserLib.GetReflectedVector( incidentVector, surfaceNormal )

	return incidentVector - 2 * ( surfaceNormal:DotProduct( incidentVector ) * surfaceNormal );

end

if ( SERVER ) then

	AddCSLuaFile( "autorun/laserlib.lua" );
	
	function LaserLib.SpawnDissolver( ent, position, attacker, dissolveType )
		Dissolver = ents.Create( "env_entity_dissolver" );
		Dissolver.Target = "laserdissolve"..ent:EntIndex();
		Dissolver:SetKeyValue( "dissolvetype", dissolveType );
		Dissolver:SetKeyValue( "magnitude", 0 );
		Dissolver:SetPos( position );
		Dissolver:SetPhysicsAttacker( attacker );
		Dissolver:Spawn();
		
		return Dissolver;
	end
	
	function LaserLib.DoDamage( target, hitPos, normal, beamDir, damage, attacker, dissolveType, pushProps, killSound, laserEnt )
	
		laserEnt.NextLaserDamage = laserEnt.NextLaserDamage or CurTime();
	
		if ( pushProps and target:GetPhysicsObject():IsValid() ) then
			local phys = target:GetPhysicsObject();
			phys:ApplyForceOffset( beamDir * phys:GetMass() * 12, hitPos );
		end
		
		if ( CurTime() >= laserEnt.NextLaserDamage ) then
			if ( target:IsVehicle() and target:GetDriver():IsValid() ) then -- we must kill the driver!
				target = target:GetDriver();
				target:Kill(); -- takedamage doesn't seem to work on a player inside a vehicle
			end		
			
			if ( target:GetClass() == "shield" ) then
				target:Hit( laserEnt, hitPos, math.Clamp( damage / 2500 * 3, 0, 4), -1*normal );
				laserEnt.NextLaserDamage = CurTime() + 0.3;
				return; -- we stop here because we hit a shield
			end
			
			if ( target:Health() <= damage ) then
				if ( target:IsNPC() or target:IsPlayer() ) then
					local dissolverEnt = LaserLib.SpawnDissolver( laserEnt, target:GetPos(), attacker, dissolveType );
					
					-- dissolving the weapon too
					if ( target:GetActiveWeapon():IsValid() ) then target:GetActiveWeapon():SetName( dissolverEnt.Target ); end
					
					target:TakeDamage( damage, attacker, laserEnt ); -- we kill the player/NPC to get his ragdoll
					
					if ( target:IsPlayer() ) then
						if ( not target:GetRagdollEntity() or not target:GetRagdollEntity():IsValid() ) then return; end
						target:GetRagdollEntity():SetName( dissolverEnt.Target ); -- thanks to Nevec for the player ragdoll idea, allowing us to dissolve him the cleanest way
					else
						if ( target.DeathRagdoll and target.DeathRagdoll:IsValid() ) then -- if Keep Corpses is disabled, DeathRagdoll is nil, so we need to check this
							target.DeathRagdoll:SetName( dissolverEnt.Target );
						else
							target:SetName( dissolverEnt.Target );
						end
					end
					
					dissolverEnt:Fire( "Dissolve", dissolverEnt.Target, 0 );
					dissolverEnt:Fire( "Kill", "", 0.1 );
				end
				
				if ( killSound ~= nil and ( target:Health() ~= 0 or target:IsPlayer() ) ) then
					WorldSound( Sound( killSound ), target:GetPos() );
					target:EmitSound( Sound( killSound ) );
					-- FIXME : sometimes the sound repeats and that's annoying --> do a better check to see if the target's dead or exclude some entities (magnusson device for example)
				end
			else
				laserEnt.NextLaserDamage = CurTime() + 0.3;
			end
			
			target:TakeDamage( damage, attacker, laserEnt );
		end
	end
	
	
	function LaserLib.AssignNPCRagdoll( entity, ragdoll )
		-- it seems that's the only clean way to get the NPC's ragdoll in the DoDamage function -- Thanks to Kogitsune
		entity.DeathRagdoll = ragdoll;
	end

	hook.Add( "CreateEntityRagdoll", "LaserLib.AssignNPCRagdoll", LaserLib.AssignNPCRagdoll );

end



if ( CLIENT ) then

	-- nothing here at the moment

end